use clap::Parser;
use serde_json::{Value, json};
use std::error::Error;
use std::fs;
use tera::{Context, Tera};
use crate::agent::{
    MarketSimulator, 
    EconomicAgent, 
    AgentType, 
    BehaviorRules,
    advanced::{
        AdvancedEconomicSimulator,
        EconomicNode,
        EconomicEdge,
        RelationType
    }
};

/// Academic Market Research Tool
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    /// Economic topic to research (e.g., gdp, inflation, unemployment)
    #[arg(short, long)]
    topic: String,

    /// Country or region code (e.g., US, CN, WLD for World)
    #[arg(short, long, default_value = "WLD")]
    country: String,

    /// Time period for analysis (e.g., 5, 10 for years)
    #[arg(short, long, default_value = "5")]
    years: String,

    /// Output file name
    #[arg(short, long, default_value = "report.html")]
    output: String,
}

/// Fetch economic data from World Bank API
fn fetch_worldbank_data(topic: &str, country: &str) -> Result<Value, Box<dyn Error>> {
    let url = format!(
        "http://api.worldbank.org/v2/country/{}/indicator/{}?format=json",
        country, topic
    );
    let resp = reqwest::blocking::get(&url)?.json::<Value>()?;
    Ok(resp)
}

/// Generate HTML report
fn generate_html_report(
    data: &Value, 
    papers: &Value, 
    args: &Args,
    simulation: &Value,
    network_data: &Value,
    network_metrics: &Value
) -> Result<(), Box<dyn Error>> {
    let mut tera = Tera::default();
    tera.add_raw_template("report.html", include_str!("templates/report.html"))?;

    let mut context = Context::new();
    context.insert("topic", &args.topic);
    context.insert("country", &args.country);
    context.insert("years", &args.years);
    context.insert("data", data);
    context.insert("papers", papers);
    context.insert("simulation", simulation);

    let html = tera.render("report.html", &context)?;
    fs::write(&args.output, html)?;
    Ok(())
}

fn main() -> Result<(), Box<dyn Error>> {
    let args = Args::parse();
    
    // Initialize market simulation
    let mut simulator = MarketSimulator::new();
    
    // Add agents based on topic
    match args.topic.as_str() {
        "inflation" => {
            simulator.add_agent(EconomicAgent {
                id: 1,
                agent_type: AgentType::Consumer,
                resources: 1000.0,
                behavior: BehaviorRules {
                    risk_aversion: 0.3,
                    spending_ratio: 0.7,
                    saving_ratio: 0.3,
                },
                history: Vec::new(),
            });
            
            simulator.add_agent(EconomicAgent {
                id: 2,
                agent_type: AgentType::Producer,
                resources: 5000.0,
                behavior: BehaviorRules {
                    risk_aversion: 0.2,
                    spending_ratio: 0.5,
                    saving_ratio: 0.5,
                },
                history: Vec::new(),
            });
        }
        _ => {
            // Default agents for other topics
            for i in 0..5 {
                simulator.add_agent(EconomicAgent {
                    id: i as u32 + 1,
                    agent_type: if i % 2 == 0 { AgentType::Consumer } else { AgentType::Producer },
                    resources: 1000.0 * (i as f64 + 1.0),
                    behavior: BehaviorRules {
                        risk_aversion: 0.1 * i as f64,
                        spending_ratio: 0.8 - 0.1 * i as f64,
                        saving_ratio: 0.2 + 0.1 * i as f64,
                    },
                    history: Vec::new(),
                });
            }
        }
    }

    // Run basic agent simulation
    let simulation_data = simulator.simulate_step();
    
    // Initialize advanced network simulation
    let mut network_simulator = AdvancedEconomicSimulator::new();
    
    // Build economic network
    let market_node = network_simulator.add_node(EconomicNode::Market);
    let institution_node = network_simulator.add_node(EconomicNode::Institution);
    
    for agent in &simulator.agents {
        let agent_node = network_simulator.add_node(EconomicNode::Agent(agent.id));
        
        // Connect agent to market
        network_simulator.add_relation(
            agent_node, 
            market_node, 
            EconomicEdge {
                relation_type: RelationType::Trade,
                strength: match agent.agent_type {
                    AgentType::Producer => 0.9,
                    AgentType::Consumer => 0.7,
                    _ => 0.5
                }
            }
        );
        
        // Connect agent to institution
        network_simulator.add_relation(
            agent_node,
            institution_node,
            EconomicEdge {
                relation_type: RelationType::Regulatory,
                strength: 0.3
            }
        );
    }
    
    // Simulate network effects
    let network_data = network_simulator.simulate_network_effects(
        market_node,
        0.8  // Initial shock strength
    );
    
    let network_metrics = network_simulator.calculate_network_metrics();
    
    // Generate report with network data
    generate_html_report(
        &economic_data, 
        &papers_data, 
        &args, 
        &simulation_data,
        &network_data,
        &network_metrics
    )?;
    
    println!("Fetching economic data for {} in {}...", args.topic, args.country);
    let economic_data = fetch_worldbank_data(&args.topic, &args.country)?;
    
    println!("Generating HTML report...");
    generate_html_report(&economic_data, &json!({}), &args, &simulation_data)?;
    
    println!("Report generated successfully: {}", args.output);
    Ok(())
}